<template>
	<view>
	</view>

</template>

<script lang="uts">
	import CameraView from 'com.otaliastudios.cameraview.CameraView';
	import FrameLayout from 'android.widget.FrameLayout';
	import CameraListener from 'com.otaliastudios.cameraview.CameraListener';
	import FileCallback from 'com.otaliastudios.cameraview.FileCallback';
	import PictureResult from 'com.otaliastudios.cameraview.PictureResult';
	import VideoResult from 'com.otaliastudios.cameraview.VideoResult';
	import Engine from 'com.otaliastudios.cameraview.controls.Engine';
	import PictureFormat from 'com.otaliastudios.cameraview.controls.PictureFormat';
	import Gesture from 'com.otaliastudios.cameraview.gesture.Gesture';
	import GestureAction from 'com.otaliastudios.cameraview.gesture.GestureAction';
	import LayoutParams from 'android.widget.FrameLayout.LayoutParams';
	import TextUtils from 'android.text.TextUtils';
	import Button from 'android.widget.Button';
	import View from 'android.view.View';
	import ViewGroup from 'android.view.ViewGroup';
	import Toast from 'android.widget.Toast';
	import Facing from 'com.otaliastudios.cameraview.controls.Facing';
	import Flash from 'com.otaliastudios.cameraview.controls.Flash';
	import File from 'java.io.File';
	import Mode from 'com.otaliastudios.cameraview.controls.Mode';
	import SizeSelector from 'com.otaliastudios.cameraview.size.SizeSelector';
	import SizeSelectors from 'com.otaliastudios.cameraview.size.SizeSelectors';
	import CameraOptions from 'com.otaliastudios.cameraview.CameraOptions';
	import PointF from 'android.graphics.PointF';
	import AspectRatio from 'com.otaliastudios.cameraview.size.AspectRatio';

	import DefaultAutoFocusMarker from 'com.otaliastudios.cameraview.markers.DefaultAutoFocusMarker';


	//原生提供以下属性或方法的实现
	export default {
		/**
		 * 组件名称，也就是开发者使用的标签
		 */
		name: "camera-view",
		/**
		 * 组件涉及的事件声明，只有声明过的事件，才能被正常发送
		 */
		emits: [
			'onPictureTaken',
			'onVideoRecordingStart',
			'onVideoRecordingEnd',
			'onAutoFocusStart',
			'onAutoFocusEnd'
		],
		/**
		 * 属性声明，组件的使用者会传递这些属性值到组件
		 */
	props: {
		"facing": {
			type: String,
			default: "back"
		},
		"flash": {
			type: String,
			default: 'off'
		},
		// 视频尺寸配置
		"maxVideoWidth": {
			type: Int,
			default: 1920
		},
		"maxVideoHeight": {
			type: Int,
			default: 1080
		},
		// 图片尺寸配置
		"maxPictureWidth": {
			type: Int,
			default: 1920
		},
		"maxPictureHeight": {
			type: Int,
			default: 1080
		},

	},
		/**
		 * 组件内部变量声明
		 */
		data() {
			return {
				rootView: null as FrameLayout | null,
				cameraView: null as CameraView | null,

			}
		},
		/**
		 * 属性变化监听器实现
		 */
		watch: {
			"maxVideoWidth": {
				handler(newValue : number, oldValue : number) {
          const width = SizeSelectors.maxWidth(this.maxVideoWidth);
          const height = SizeSelectors.maxHeight(this.maxVideoHeight);
					this.cameraView?.setVideoSize(SizeSelectors.or(width, height));
				},
				immediate: false // 创建时是否通过此方法更新属性，默认值为false
			},
			"maxVideoHeight": {
				handler(newValue : number, oldValue : number) {
          const width = SizeSelectors.maxWidth(this.maxVideoWidth);
          const height = SizeSelectors.maxHeight(this.maxVideoHeight);
					this.cameraView?.setVideoSize(SizeSelectors.or(width, height));
				},
				immediate: false // 创建时是否通过此方法更新属性，默认值为false
			},
			"maxPictureWidth": {
				handler(newValue : number, oldValue : number) {
          const width = SizeSelectors.maxWidth(this.maxPictureWidth);
          const height = SizeSelectors.maxHeight(this.maxPictureHeight);
					this.cameraView?.setPictureSize(SizeSelectors.or(width, height));
				},
				immediate: false // 创建时是否通过此方法更新属性，默认值为false
			},
			"maxPictureHeight": {
				handler(newValue : number, oldValue : number) {
          const width = SizeSelectors.maxWidth(this.maxPictureWidth);
          const height = SizeSelectors.maxHeight(this.maxPictureHeight);
					this.cameraView?.setPictureSize(SizeSelectors.or(width, height));
				},
				immediate: false // 创建时是否通过此方法更新属性，默认值为false
			},
			"facing": {
				handler(newValue : string, oldValue : string) {
					if (!TextUtils.isEmpty(newValue)) {
						if (newValue == 'back') {
							this.cameraView?.setFacing(Facing.BACK);
						} else {
							this.cameraView?.setFacing(Facing.FRONT);
						}
					}
				},
				immediate: false // 创建时是否通过此方法更新属性，默认值为false
			},
			"flash": {
				handler(newValue : string, oldValue : string) {
					switch (newValue) {
						case 'on':
							this.cameraView?.setFlash(Flash.ON);
							break;
						case 'auto':
							this.cameraView?.setFlash(Flash.AUTO);
							break;
						case 'torch':
							this.cameraView?.setFlash(Flash.TORCH);
							break;
						case 'off':
							this.cameraView?.setFlash(Flash.OFF);
							break;
					}
				},
				immediate: false // 创建时是否通过此方法更新属性，默认值为false
			}
		},
		/**
		 * 规则：如果没有配置expose，则methods中的方法均对外暴露，如果配置了expose，则以expose的配置为准向外暴露
		 * ['publicMethod'] 含义为：只有 `publicMethod` 在实例上可用
		 */
		expose: ['close', 'open', 'takePicture', 'takePictureSnapshot', 'stopVideo', 'setZoom', 'takeVideo'],
		methods: {
			close() {
				this.cameraView?.close();
			},
			open() {
				this.cameraView?.open();
			},
			takePicture() {
				this.cameraView?.setMode(Mode.PICTURE);
				this.cameraView?.takePicture();
			},
			takePictureSnapshot() {
				this.cameraView?.setMode(Mode.PICTURE);
				this.cameraView?.takePictureSnapshot();
			},
			takeVideo() {
				this.cameraView?.setMode(Mode.VIDEO);
        // this.cameraView?.setZoom(1.0.toFloat());
				const videoFile : File = new File(this.$androidContext!.getExternalCacheDir(), Date.now() + '.mp4');
				this.cameraView?.takeVideo(videoFile);
			},
			takeVideoSnapshot(duration : Int = 0) {
				this.cameraView?.setMode(Mode.VIDEO);
				const videoFile : File = new File(this.$androidContext!.getExternalCacheDir(), Date.now() + '.mp4');
				this.cameraView?.takeVideoSnapshot(videoFile);

			},
			stopVideo() {
				this.cameraView?.stopVideo();
			},
			setZoom(zoom : Float) {
				this.cameraView?.setZoom(zoom);
			},

			isTakingVideo() : Boolean | null {
				return this.cameraView?.isTakingVideo();
			},
			isTakingPicture() : Boolean | null {
				return this.cameraView?.isTakingPicture();
			},
			isOpened() : Boolean | null {
				return this.cameraView?.isOpened();
			},


		},
		/**
		 * [可选实现] 组件被创建，组件第一个生命周期，
		 * 在内存中被占用的时候被调用，开发者可以在这里执行一些需要提前执行的初始化逻辑
		 */
		created() {
		},
		/**
		 * [可选实现] 对应平台的view载体即将被创建，对应前端beforeMount
		 */
		NVBeforeLoad() {

		},
		/**
		 * [必须实现] 创建原生View，必须定义返回值类型
		 * 开发者需要重点实现这个函数，声明原生组件被创建出来的过程，以及最终生成的原生组件类型
		 * （Android需要明确知道View类型，需特殊校验）
		 */
		NVLoad() : FrameLayout {
			this.rootView = new FrameLayout(this.$androidContext!);
			this.cameraView = new CameraView(this.$androidContext!);

			this.rootView?.addView(this.cameraView);
			return this.rootView!;


		},
		/**
		 * [可选实现] 原生View已创建
		 */
		NVLoaded() {

			let layoutParams = new LayoutParams(
				LayoutParams.MATCH_PARENT,
				LayoutParams.MATCH_PARENT
			);
			this.cameraView?.mapGesture(Gesture.TAP, GestureAction.AUTO_FOCUS); // 点击进行对焦
			this.cameraView?.mapGesture(Gesture.PINCH, GestureAction.ZOOM); // 点击进行对焦
			this.cameraView?.setPictureFormat(PictureFormat.JPEG);
			this.cameraView?.setLayoutParams(layoutParams);
			this.cameraView?.setEngine(Engine.CAMERA2);

			this.cameraView?.setKeepScreenOn(true);
			this.cameraView?.setExperimental(true);
			this.cameraView?.setAutoFocusMarker(new DefaultAutoFocusMarker());



			this.cameraView?.addCameraListener(new CameraListenerImpl(this));
			this.cameraView?.setLifecycleOwner(null);

			let permission = ["android.permission.RECORD_AUDIO", "android.permission.CAMERA", "android.permission.WRITE_EXTERNAL_STORAGE"]
			UTSAndroid.requestSystemPermission(UTSAndroid.getUniActivity()!, permission, function (allRight, grantedList) {
				if (allRight) {

					// 使用传入的尺寸配置，如果没有传入则使用默认值
					const videoWidth = SizeSelectors.maxWidth(this.maxVideoWidth);
					const videoHeight = SizeSelectors.maxHeight(this.maxVideoHeight);
					const videoDimensions = SizeSelectors.or(videoWidth, videoHeight);

					const pictureWidth = SizeSelectors.maxWidth(this.maxPictureWidth);
					const pictureHeight = SizeSelectors.maxHeight(this.maxPictureHeight);
					const pictureDimensions = SizeSelectors.or(pictureWidth, pictureHeight);

					this.cameraView?.setPictureSize(pictureDimensions);
					this.cameraView?.setVideoSize(videoDimensions);

					this.cameraView?.setLifecycleOwner(null);

					this.cameraView?.setAutoFocusMarker(new DefaultAutoFocusMarker());



					// 用户同意了全部权限
					this.cameraView?.open();
				} else {
					// 用户仅同意了 grantedList中的权限
				}
			}, function (doNotAskAgain, grantedList) {

				if (doNotAskAgain) {
					// 	Toast.makeText(UTSAndroid.getAppContext(),"屏幕状态监听已注册，注意观察控制台日志",Toast.LENGTH_LONG).show();
				}
			})

			UTSAndroid.onAppActivityPause(() => {
				this.cameraView?.close();
			});

			UTSAndroid.onAppActivityResume(() => {
				this.cameraView?.open();
			});


		},
		/**
		 * [可选实现] 原生View布局完成
		 */
		NVLayouted() {
		},
		/**
		 * [可选实现] 原生View将释放
		 */
		NVBeforeUnload() {

		},
		/**
		 * [可选实现] 原生View已释放，这里可以做释放View之后的操作
		 */
		NVUnloaded() {
			if (this.$el != null) { // 如果组件绑定了视图则需要在组件销毁时释放视图相关资源
				this.cameraView?.destroy();
				this.cameraView = null;
			}


		},
		/**
		 * [可选实现] 组件销毁
		 */
		unmounted() {

			UTSAndroid.offAppActivityPause();

			UTSAndroid.offAppActivityResume();

		},
		/**
		 * [可选实现] 自定组件布局尺寸，用于告诉排版系统，组件自身需要的宽高
		 * 一般情况下，组件的宽高应该是由终端系统的排版引擎决定，组件开发者不需要实现此函数
		 * 但是部分场景下，组件开发者需要自己维护宽高，则需要开发者重写此函数
		 */
		NVMeasure(size : UTSSize) : UTSSize {
			// size.width = 300.0.toFloat();
			// size.height = 200.0.toFloat();
			return size;
		}
	}



	class CameraListenerImpl implements CameraListener {

		private comp : CameraViewComponent;

		constructor(comp : CameraViewComponent) {
			super();
			this.comp = comp;
		}

		override onCameraOpened(options : CameraOptions) {
			this.comp.$emit('onCameraOpened')
		}



		override onPictureTaken(result : PictureResult) : void {
			const file = new File(this.comp.$androidContext!.getExternalCacheDir(), Date.now() + '.jpeg');
			result.toFile(file, new UtsFileCallback((res : File) => {
				const detail = {
					path: res.getAbsolutePath(),
					width: result.getSize().width,
					height: result.getSize().height,
				}
				this.comp.$emit('onPictureTaken', detail)
			}));
		}
		override onVideoTaken(result : VideoResult) : void {

			const detail = {
				path: result.getFile().getAbsolutePath(),
				size: result.getSize()
			}
			this.comp.$emit('onVideoRecordingEnd', detail)

		}
		override onVideoRecordingStart() : void {
			this.comp.$emit('onVideoRecordingStart')
		}
		override onVideoRecordingEnd() : void {
			// this.comp.$emit('onVideoRecordingEnd')

		}


		override onAutoFocusStart(point : PointF) : void {
			this.comp.$emit('onAutoFocusStart', { x: point.x, y: point.y })
		}
		override onAutoFocusEnd(focus : Boolean, point : PointF) : void {
			this.comp.$emit('onAutoFocusEnd', {
				x: point.x,
				y: point.y,
				focus
			})
		}
	}



	class UtsFileCallback implements FileCallback {

		callback : (file : File) => void

		constructor(cb : (file : File) => void) {
			super();
			this.callback = cb;

		}
		override onFileReady(file ?: File) : void {
			this.callback(file!)
		}

	}



	export class AppHookProxy implements UTSAndroidHookProxy {
		override onCreate(application : Application) {
			//当前应用是否 取得用户同意隐私协议
			Log.d("AppHookProxy", "AppHookProxy--onCreate---")


			application.registerActivityLifecycleCallbacks(new MyLifecycleCallbacks());

		}
	}
</script>

<style>

</style>